home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / amitcp / netinet / in.c < prev    next >
C/C++ Source or Header  |  1993-08-12  |  17KB  |  657 lines

  1. RCS_ID_C="$Id: in.c,v 1.11 1993/06/04 11:16:15 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * HISTORY
  8.  * $Log: in.c,v $
  9.  * Revision 1.11  1993/06/04  11:16:15  jraja
  10.  * Fixes for first public release.
  11.  *
  12.  * Revision 1.10  1993/05/17  00:16:44  ppessi
  13.  * Changed RCS version. Added rcsid to each file.
  14.  *
  15.  * Revision 1.9  93/05/02  17:32:55  17:32:55  jraja (Jarno Tapio Rajahalme)
  16.  * Removed separate inclusion of route protos.
  17.  * 
  18.  * Revision 1.8  93/04/13  22:06:14  22:06:14  jraja (Jarno Tapio Rajahalme)
  19.  * Added casts to if_ioctl -calls to comply with the prototype.
  20.  * 
  21.  * Revision 1.7  93/04/05  19:05:48  19:05:48  jraja (Jarno Tapio Rajahalme)
  22.  * Changed storage of the spl functions  return values to type spl_t.
  23.  * Added include for conf.h to every .c file.
  24.  * 
  25.  * Revision 1.6  93/03/13  17:14:15  17:14:15  ppessi (Pekka Pessi)
  26.  * Fixed bugs with variable initialization.
  27.  * 
  28.  * Revision 1.5  93/03/05  21:09:15  21:09:15  jraja (Jarno Tapio Rajahalme)
  29.  * Fixed includes (again).
  30.  * 
  31.  * Revision 1.4  93/03/05  03:19:23  03:19:23  ppessi (Pekka Pessi)
  32.  * Compiles with SASC. Initial test version.
  33.  * 
  34.  * Revision 1.3  93/03/03  21:55:57  21:55:57  jraja (Jarno Tapio Rajahalme)
  35.  * Moved some data definitions from in_var.h to here.
  36.  * 
  37.  * Revision 1.2  93/02/26  08:53:41  08:53:41  jraja (Jarno Tapio Rajahalme)
  38.  * Made this compile with ANSI C.
  39.  * 
  40.  * Revision 1.1  92/11/17  16:28:34  16:28:34  jraja (Jarno Tapio Rajahalme)
  41.  * Initial revision
  42.  */
  43.  
  44. /*
  45.  * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
  46.  * All rights reserved.
  47.  *
  48.  * Redistribution and use in source and binary forms, with or without
  49.  * modification, are permitted provided that the following conditions
  50.  * are met:
  51.  * 1. Redistributions of source code must retain the above copyright
  52.  *    notice, this list of conditions and the following disclaimer.
  53.  * 2. Redistributions in binary form must reproduce the above copyright
  54.  *    notice, this list of conditions and the following disclaimer in the
  55.  *    documentation and/or other materials provided with the distribution.
  56.  * 3. All advertising materials mentioning features or use of this software
  57.  *    must display the following acknowledgement:
  58.  *    This product includes software developed by the University of
  59.  *    California, Berkeley and its contributors.
  60.  * 4. Neither the name of the University nor the names of its contributors
  61.  *    may be used to endorse or promote products derived from this software
  62.  *    without specific prior written permission.
  63.  *
  64.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  65.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  66.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  67.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  68.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  69.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  70.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  71.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  72.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  73.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  74.  * SUCH DAMAGE.
  75.  *
  76.  *    @(#)in.c    7.17 (Berkeley) 4/20/91
  77.  */
  78.  
  79. #include <conf.h>
  80.  
  81. #include <sys/param.h>
  82. #include <sys/systm.h>
  83. #include <sys/ioctl.h>
  84. #include <sys/malloc.h>
  85. #include <sys/mbuf.h>
  86. #include <sys/socket.h>
  87. #include <sys/socketvar.h>
  88. #include <sys/synch.h>
  89.  
  90. #include <netinet/in_systm.h>
  91. #include <net/if.h>
  92. #include <net/route.h>
  93. #include <netinet/in.h>
  94. #include <netinet/in_var.h>
  95.  
  96. #include <netinet/in_protos.h>
  97.  
  98. #if INET
  99. /*
  100.  * Formulate an Internet address from network + host.
  101.  */
  102. struct in_addr
  103. in_makeaddr(net, host)
  104.     u_long net, host;
  105. {
  106.     register struct in_ifaddr *ia;
  107.     register u_long mask;
  108.     u_long addr;
  109.  
  110.     if (IN_CLASSA(net))
  111.         mask = IN_CLASSA_HOST;
  112.     else if (IN_CLASSB(net))
  113.         mask = IN_CLASSB_HOST;
  114.     else
  115.         mask = IN_CLASSC_HOST;
  116.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  117.         if ((ia->ia_netmask & net) == ia->ia_net) {
  118.             mask = ~ia->ia_subnetmask;
  119.             break;
  120.         }
  121.     addr = htonl(net | (host & mask));
  122.     return (*(struct in_addr *)&addr);
  123. }
  124.  
  125. /*
  126.  * Return the network number from an internet address.
  127.  */
  128. u_long
  129. in_netof(in)
  130.     struct in_addr in;
  131. {
  132.     register u_long i = ntohl(in.s_addr);
  133.     register u_long net;
  134.     register struct in_ifaddr *ia;
  135.  
  136.     if (IN_CLASSA(i))
  137.         net = i & IN_CLASSA_NET;
  138.     else if (IN_CLASSB(i))
  139.         net = i & IN_CLASSB_NET;
  140.     else if (IN_CLASSC(i))
  141.         net = i & IN_CLASSC_NET;
  142.     else
  143.         return (0);
  144.  
  145.     /*
  146.      * Check whether network is a subnet;
  147.      * if so, return subnet number.
  148.      */
  149.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  150.         if (net == ia->ia_net)
  151.             return (i & ia->ia_subnetmask);
  152.     return (net);
  153. }
  154.  
  155. /*
  156.  * Compute and save network mask as sockaddr from an internet address.
  157.  */
  158. void
  159. in_sockmaskof(in, sockmask)
  160.     struct in_addr in;
  161.     register struct sockaddr_in *sockmask;
  162. {
  163.     register u_long net;
  164.     register u_long mask;
  165.     {
  166.     register u_long i = ntohl(in.s_addr);
  167.  
  168.     if (i == 0)
  169.         net = 0, mask = 0;
  170.     else if (IN_CLASSA(i))
  171.         net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET;
  172.     else if (IN_CLASSB(i))
  173.         net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET;
  174.     else if (IN_CLASSC(i))
  175.         net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET;
  176.     else
  177.         net = i, mask = -1;
  178.     }
  179.     {
  180.     register struct in_ifaddr *ia;
  181.     /*
  182.      * Check whether network is a subnet;
  183.      * if so, return subnet number.
  184.      */
  185.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  186.         if (net == ia->ia_net)
  187.             mask =  ia->ia_subnetmask;
  188.     }
  189.     {
  190.     register char *cpbase = (char *)&(sockmask->sin_addr);
  191.     register char *cp = (char *)(1 + &(sockmask->sin_addr));
  192.  
  193.     sockmask->sin_addr.s_addr = htonl(mask);
  194.     sockmask->sin_len = 0;
  195.     while (--cp >= cpbase)
  196.         if (*cp) {
  197.             sockmask->sin_len = 1 + cp - (caddr_t)sockmask;
  198.             break;
  199.         }
  200.     }
  201. }
  202.  
  203. /*
  204.  * Return the host portion of an internet address.
  205.  */
  206. u_long
  207. in_lnaof(in)
  208.     struct in_addr in;
  209. {
  210.     register u_long i = ntohl(in.s_addr);
  211.     register u_long net, host;
  212.     register struct in_ifaddr *ia;
  213.  
  214.     if (IN_CLASSA(i)) {
  215.         net = i & IN_CLASSA_NET;
  216.         host = i & IN_CLASSA_HOST;
  217.     } else if (IN_CLASSB(i)) {
  218.         net = i & IN_CLASSB_NET;
  219.         host = i & IN_CLASSB_HOST;
  220.     } else if (IN_CLASSC(i)) {
  221.         net = i & IN_CLASSC_NET;
  222.         host = i & IN_CLASSC_HOST;
  223.     } else
  224.         return (i);
  225.  
  226.     /*
  227.      * Check whether network is a subnet;
  228.      * if so, use the modified interpretation of `host'.
  229.      */
  230.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  231.         if (net == ia->ia_net)
  232.             return (host &~ ia->ia_subnetmask);
  233.     return (host);
  234. }
  235.  
  236. #ifndef SUBNETSARELOCAL
  237. #define    SUBNETSARELOCAL    1
  238. #endif
  239. int subnetsarelocal = SUBNETSARELOCAL;
  240. /*
  241.  * Return 1 if an internet address is for a ``local'' host
  242.  * (one to which we have a connection).  If subnetsarelocal
  243.  * is true, this includes other subnets of the local net.
  244.  * Otherwise, it includes only the directly-connected (sub)nets.
  245.  */
  246. int
  247. in_localaddr(in)
  248.     struct in_addr in;
  249. {
  250.     register u_long i = ntohl(in.s_addr);
  251.     register struct in_ifaddr *ia;
  252.  
  253.     if (subnetsarelocal) {
  254.         for (ia = in_ifaddr; ia; ia = ia->ia_next)
  255.             if ((i & ia->ia_netmask) == ia->ia_net)
  256.                 return (1);
  257.     } else {
  258.         for (ia = in_ifaddr; ia; ia = ia->ia_next)
  259.             if ((i & ia->ia_subnetmask) == ia->ia_subnet)
  260.                 return (1);
  261.     }
  262.     return (0);
  263. }
  264.  
  265. /*
  266.  * Determine whether an IP address is in a reserved set of addresses
  267.  * that may not be forwarded, or whether datagrams to that destination
  268.  * may be forwarded.
  269.  */
  270. int
  271. in_canforward(in)
  272.     struct in_addr in;
  273. {
  274.     register u_long i = ntohl(in.s_addr);
  275.     register u_long net;
  276.  
  277.     if (IN_EXPERIMENTAL(i))
  278.         return (0);
  279.     if (IN_CLASSA(i)) {
  280.         net = i & IN_CLASSA_NET;
  281.         if (net == 0 || net == IN_LOOPBACKNET)
  282.             return (0);
  283.     }
  284.     return (1);
  285. }
  286.  
  287. int    in_interfaces;        /* number of external internet interfaces */
  288. extern    struct ifnet loif;
  289.  
  290. /*
  291.  * Generic internet control operations (ioctl's).
  292.  * Ifp is 0 if not an interface-specific ioctl.
  293.  */
  294. int
  295. in_control(so, cmd, data, ifp)
  296.     struct socket *so;
  297.     int cmd;
  298.     caddr_t data;
  299.     register struct ifnet *ifp;
  300. {
  301.     register struct ifreq *ifr = (struct ifreq *)data;
  302.     register struct in_ifaddr *ia = 0;
  303.     register struct ifaddr *ifa;
  304.     struct in_ifaddr *oia;
  305.     struct in_aliasreq *ifra = (struct in_aliasreq *)data;
  306.     struct mbuf *m;
  307.     struct sockaddr_in oldaddr;
  308.     int error, hostIsNew, maskIsNew;
  309.     u_long i;
  310.  
  311.     /*
  312.      * Find address for this interface, if it exists.
  313.      */
  314.     if (ifp)
  315.         for (ia = in_ifaddr; ia; ia = ia->ia_next)
  316.             if (ia->ia_ifp == ifp)
  317.                 break;
  318.  
  319.     switch (cmd) {
  320.  
  321.     case SIOCAIFADDR:
  322.     case SIOCDIFADDR:
  323.         if (ifra->ifra_addr.sin_family == AF_INET)
  324.             for (oia = ia; ia; ia = ia->ia_next) {
  325.             if (ia->ia_ifp == ifp  &&
  326.                 ia->ia_addr.sin_addr.s_addr ==
  327.                 ifra->ifra_addr.sin_addr.s_addr)
  328.                 break;
  329.         }
  330.         if (cmd == SIOCDIFADDR && ia == 0)
  331.             return (EADDRNOTAVAIL);
  332.         /* FALLTHROUGH */
  333.     case SIOCSIFADDR:
  334.     case SIOCSIFNETMASK:
  335.     case SIOCSIFDSTADDR:
  336.         if ((so->so_state & SS_PRIV) == 0)
  337.             return (EPERM);
  338.  
  339.         if (ifp == 0)
  340.             panic("in_control");
  341.         if (ia == (struct in_ifaddr *)0) {
  342.             m = m_getclr(M_WAIT, MT_IFADDR);
  343.             if (m == (struct mbuf *)NULL)
  344.                 return (ENOBUFS);
  345.             if (ia = in_ifaddr) {
  346.                 for ( ; ia->ia_next; ia = ia->ia_next)
  347.                     ;
  348.                 ia->ia_next = mtod(m, struct in_ifaddr *);
  349.             } else
  350.                 in_ifaddr = mtod(m, struct in_ifaddr *);
  351.             ia = mtod(m, struct in_ifaddr *);
  352.             if (ifa = ifp->if_addrlist) {
  353.                 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
  354.                     ;
  355.                 ifa->ifa_next = (struct ifaddr *) ia;
  356.             } else
  357.                 ifp->if_addrlist = (struct ifaddr *) ia;
  358.             ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  359.             ia->ia_ifa.ifa_dstaddr
  360.                     = (struct sockaddr *)&ia->ia_dstaddr;
  361.             ia->ia_ifa.ifa_netmask
  362.                     = (struct sockaddr *)&ia->ia_sockmask;
  363.             ia->ia_sockmask.sin_len = 8;
  364.             if (ifp->if_flags & IFF_BROADCAST) {
  365.                 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
  366.                 ia->ia_broadaddr.sin_family = AF_INET;
  367.             }
  368.             ia->ia_ifp = ifp;
  369.             if (ifp != &loif)
  370.                 in_interfaces++;
  371.         }
  372.         break;
  373.  
  374.     case SIOCSIFBRDADDR:
  375.         if ((so->so_state & SS_PRIV) == 0)
  376.             return (EPERM);
  377.         /* FALLTHROUGH */
  378.  
  379.     case SIOCGIFADDR:
  380.     case SIOCGIFNETMASK:
  381.     case SIOCGIFDSTADDR:
  382.     case SIOCGIFBRDADDR:
  383.         if (ia == (struct in_ifaddr *)0)
  384.             return (EADDRNOTAVAIL);
  385.         break;
  386.  
  387.     default:
  388.         return (EOPNOTSUPP);
  389.         break;
  390.     }
  391.     switch (cmd) {
  392.  
  393.     case SIOCGIFADDR:
  394.         *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
  395.         break;
  396.  
  397.     case SIOCGIFBRDADDR:
  398.         if ((ifp->if_flags & IFF_BROADCAST) == 0)
  399.             return (EINVAL);
  400.         *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
  401.         break;
  402.  
  403.     case SIOCGIFDSTADDR:
  404.         if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  405.             return (EINVAL);
  406.         *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
  407.         break;
  408.  
  409.     case SIOCGIFNETMASK:
  410.         *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
  411.         break;
  412.  
  413.     case SIOCSIFDSTADDR:
  414.         if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  415.             return (EINVAL);
  416.         oldaddr = ia->ia_dstaddr;
  417.         ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
  418.         if (ifp->if_ioctl &&
  419.             (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
  420.             ia->ia_dstaddr = oldaddr;
  421.             return (error);
  422.         }
  423.         if (ia->ia_flags & IFA_ROUTE) {
  424.             ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
  425.             rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  426.             ia->ia_ifa.ifa_dstaddr =
  427.                     (struct sockaddr *)&ia->ia_dstaddr;
  428.             rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  429.         }
  430.         break;
  431.  
  432.     case SIOCSIFBRDADDR:
  433.         if ((ifp->if_flags & IFF_BROADCAST) == 0)
  434.             return (EINVAL);
  435.         ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
  436.         break;
  437.  
  438.     case SIOCSIFADDR:
  439.         return (in_ifinit(ifp, ia,
  440.             (struct sockaddr_in *) &ifr->ifr_addr, 1));
  441.  
  442.     case SIOCSIFNETMASK:
  443.         i = ifra->ifra_addr.sin_addr.s_addr;
  444.         ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
  445.         break;
  446.  
  447.     case SIOCAIFADDR:
  448.         maskIsNew = 0;
  449.         hostIsNew = 1;
  450.         error = 0;
  451.         if (ia->ia_addr.sin_family == AF_INET) {
  452.             if (ifra->ifra_addr.sin_len == 0) {
  453.                 ifra->ifra_addr = ia->ia_addr;
  454.                 hostIsNew = 0;
  455.             } else if (ifra->ifra_addr.sin_addr.s_addr ==
  456.                            ia->ia_addr.sin_addr.s_addr)
  457.                 hostIsNew = 0;
  458.         }
  459.         if (ifra->ifra_mask.sin_len) {
  460.             in_ifscrub(ifp, ia);
  461.             ia->ia_sockmask = ifra->ifra_mask;
  462.             ia->ia_subnetmask =
  463.                  ntohl(ia->ia_sockmask.sin_addr.s_addr);
  464.             maskIsNew = 1;
  465.         }
  466.         if ((ifp->if_flags & IFF_POINTOPOINT) &&
  467.             (ifra->ifra_dstaddr.sin_family == AF_INET)) {
  468.             in_ifscrub(ifp, ia);
  469.             ia->ia_dstaddr = ifra->ifra_dstaddr;
  470.             maskIsNew  = 1; /* We lie; but the effect's the same */
  471.         }
  472.         if (ifra->ifra_addr.sin_family == AF_INET &&
  473.             (hostIsNew || maskIsNew))
  474.             error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  475.         if ((ifp->if_flags & IFF_BROADCAST) &&
  476.             (ifra->ifra_broadaddr.sin_family == AF_INET))
  477.             ia->ia_broadaddr = ifra->ifra_broadaddr;
  478.         return (error);
  479.  
  480.     case SIOCDIFADDR:
  481.         in_ifscrub(ifp, ia);
  482.         if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
  483.             ifp->if_addrlist = ifa->ifa_next;
  484.         else {
  485.             while (ifa->ifa_next &&
  486.                    (ifa->ifa_next != (struct ifaddr *)ia))
  487.                     ifa = ifa->ifa_next;
  488.             if (ifa->ifa_next)
  489.                 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
  490.             else
  491.                 printf("Couldn't unlink inifaddr from ifp\n");
  492.         }
  493.         oia = ia;
  494.         if (oia == (ia = in_ifaddr))
  495.             in_ifaddr = ia->ia_next;
  496.         else {
  497.             while (ia->ia_next && (ia->ia_next != oia))
  498.                 ia = ia->ia_next;
  499.             if (ia->ia_next)
  500.                 ia->ia_next = oia->ia_next;
  501.             else
  502.                 printf("Didn't unlink inifadr from list\n");
  503.         }
  504.         (void) m_free(dtom(oia));
  505.         break;
  506.  
  507.     default:
  508.         if (ifp == 0 || ifp->if_ioctl == 0)
  509.             return (EOPNOTSUPP);
  510.         return ((*ifp->if_ioctl)(ifp, cmd, data));
  511.     }
  512.     return (0);
  513. }
  514.  
  515. /*
  516.  * Delete any existing route for an interface.
  517.  */
  518. void
  519. in_ifscrub(ifp, ia)
  520.     register struct ifnet *ifp;
  521.     register struct in_ifaddr *ia;
  522. {
  523.  
  524.     if ((ia->ia_flags & IFA_ROUTE) == 0)
  525.         return;
  526.     if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
  527.         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  528.     else
  529.         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
  530.     ia->ia_flags &= ~IFA_ROUTE;
  531. }
  532.  
  533. /*
  534.  * Initialize an interface's internet address
  535.  * and routing table entry.
  536.  */
  537. int
  538. in_ifinit(ifp, ia, sin, scrub)
  539.     register struct ifnet *ifp;
  540.     register struct in_ifaddr *ia;
  541.     struct sockaddr_in *sin;
  542.         int scrub;
  543. {
  544.     register u_long i = ntohl(sin->sin_addr.s_addr);
  545.     struct sockaddr_in oldaddr;
  546.     int error, flags = RTF_UP;
  547.     spl_t s = splimp();
  548.  
  549.     oldaddr = ia->ia_addr;
  550.     ia->ia_addr = *sin;
  551.     /*
  552.      * Give the interface a chance to initialize
  553.      * if this is its first address,
  554.      * and to validate the address if necessary.
  555.      */
  556.     if (ifp->if_ioctl 
  557.         && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
  558.         splx(s);
  559.         ia->ia_addr = oldaddr;
  560.         return (error);
  561.     }
  562.     splx(s);
  563.     if (scrub) {
  564.         ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
  565.         in_ifscrub(ifp, ia);
  566.         ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  567.     }
  568.     if (IN_CLASSA(i))
  569.         ia->ia_netmask = IN_CLASSA_NET;
  570.     else if (IN_CLASSB(i))
  571.         ia->ia_netmask = IN_CLASSB_NET;
  572.     else
  573.         ia->ia_netmask = IN_CLASSC_NET;
  574.     ia->ia_net = i & ia->ia_netmask;
  575.     /*
  576.      * The subnet mask includes at least the standard network part,
  577.      * but may already have been set to a larger value.
  578.      */
  579.     ia->ia_subnetmask |= ia->ia_netmask;
  580.     ia->ia_subnet = i & ia->ia_subnetmask;
  581.     ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
  582.     {
  583.         register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr));
  584.         register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr);
  585.         while (--cp >= cpbase)
  586.             if (*cp) {
  587.                 ia->ia_sockmask.sin_len =
  588.                     1 + cp - (char *) &(ia->ia_sockmask);
  589.                 break;
  590.             }
  591.     }
  592.     /*
  593.      * Add route for the network.
  594.      */
  595.     if (ifp->if_flags & IFF_BROADCAST) {
  596.         ia->ia_broadaddr.sin_addr = 
  597.             in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
  598.         ia->ia_netbroadcast.s_addr =
  599.             htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
  600.     } else if (ifp->if_flags & IFF_LOOPBACK) {
  601.         ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
  602.         flags |= RTF_HOST;
  603.     } else if (ifp->if_flags & IFF_POINTOPOINT) {
  604.         if (ia->ia_dstaddr.sin_family != AF_INET)
  605.             return (0);
  606.         flags |= RTF_HOST;
  607.     }
  608.     if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
  609.         ia->ia_flags |= IFA_ROUTE;
  610.     return (error);
  611. }
  612.  
  613. /*
  614.  * Return address info for specified internet network.
  615.  */
  616. struct in_ifaddr *
  617. in_iaonnetof(net)
  618.     u_long net;
  619. {
  620.     register struct in_ifaddr *ia;
  621.  
  622.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  623.         if (ia->ia_subnet == net)
  624.             return (ia);
  625.     return ((struct in_ifaddr *)0);
  626. }
  627.  
  628. /*
  629.  * Return 1 if the address might be a local broadcast address.
  630.  */
  631. int
  632. in_broadcast(in)
  633.     struct in_addr in;
  634. {
  635.     register struct in_ifaddr *ia;
  636.     u_long t;
  637.  
  638.     /*
  639.      * Look through the list of addresses for a match
  640.      * with a broadcast address.
  641.      */
  642.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  643.         if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
  644.         if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr)
  645.              return (1);
  646.         /*
  647.          * Check for old-style (host 0) broadcast.
  648.          */
  649.         if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
  650.             return (1);
  651.     }
  652.     if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
  653.         return (1);
  654.     return (0);
  655. }
  656. #endif
  657.